﻿''' <summary>
''' This class requires web references to HISCentral and Cuahsi found at:
''' http://hiscentral.cuahsi.org/pub_services.aspx
''' </summary>
Public Class clsCuahsi
    Inherits clsWebProvider

    Private WithEvents Cuahsi_1_0 As New Cuahsi_1_0.WaterOneFlow
    Private WithEvents Cuahsi_1_1 As New Cuahsi_1_1.WaterOneFlow
    Private WithEvents HISCentralService As New HISCentral.hiscentral

    Public Overrides ReadOnly Property Description As String
        Get
            Return "CUAHSI (Consortium of Universities for the Advancement of Hydrologic Science, Inc.) provides web services to access many types of data including USEPA STORET water quality data, NWS NCDC weather data, USGS NWIS streamflow, water quality, and groundwater levels, and many other national, regional and local data repositories. For information see: http://his.cuahsi.org."
        End Get
    End Property

    Public Overrides ReadOnly Property URL As String
        Get
            Return "http://his.cuahsi.org"
        End Get
    End Property

    ''' <summary>
    ''' When set lat/long box area of interest, retrieve list of network in the box
    ''' </summary>
    ''' <value></value>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Property AreaOfInterest As System.Drawing.RectangleF
        Get
            Return MyBase.AreaOfInterest
        End Get
        Set(value As System.Drawing.RectangleF)
            MyBase.AreaOfInterest = value
            Cancelled = False
            If value.IsEmpty Then Exit Property
            Dim arNetworks() As HISCentral.ServiceInfo = HISCentralService.GetServicesInBox2(AreaOfInterest.Left, AreaOfInterest.Bottom, AreaOfInterest.Right, AreaOfInterest.Top)
            dictNetworks.Clear()
            For i As Integer = 0 To arNetworks.Length - 1
                dictNetworks.Add(arNetworks(i).NetworkName, arNetworks(i))
            Next
        End Set
    End Property

    ''' <summary>
    ''' After one or more networks are selected, get list of all time series then all stations and parameters
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function GetStations(Optional NameFilter As String = "") As Boolean
        Cancelled = False
        dictStations.Clear()
        dictAgencies.Clear()
        dictParameters.Clear()
        If Not GetSeries() Then Return False
        For Each ser As HISCentral.SeriesRecord In dictSeries.Values
            With ser
                Dim sta As String = .location
                If Not dictStations.ContainsKey(sta) Then
                    Dim AgencyID As String = .ServCode
                    Dim AgencyName As String = .ServCode
                    Dim County As String = "", State As String = ""
                    Dim Fips As String = ""
                    If dictNetworks.ContainsKey(AgencyID) Then AgencyName = dictNetworks(AgencyID).Title
                    If NameFilter = "" OrElse .Sitename.ToUpper.Contains(NameFilter.ToUpper) Then
                        dictStations.Add(sta, New clsStation(.location, .location, .Sitename, "", AgencyID, AgencyName, .latitude, .longitude, Fips, ""))
                        If Not dictAgencies.ContainsKey(AgencyID) Then dictAgencies.Add(AgencyID, New clsAgency(AgencyID, AgencyName))
                    End If
                End If
            End With
        Next
        Return True
    End Function

    ''' <summary>
    ''' After one or more stations are selected, get list of parameters associated with those stations
    ''' </summary>
    ''' <returns></returns>
    ''' <remarks></remarks>
    Public Overrides Function GetParameters(Optional NameFilter As String = "") As Boolean
        Cancelled = False
        dictParameters.Clear()
        For Each ser As HISCentral.SeriesRecord In dictSeries.Values
            With ser
                Dim Sta As String = .location
                Dim PCode As String = .VarCode
                If SelectedStations.Contains(Sta) Then
                    If NameFilter = "" OrElse .VarName.ToUpper.Contains(NameFilter.ToUpper) Then
                        If Not dictParameters.ContainsKey(PCode) Then dictParameters.Add(PCode, New clsParameter(.location, .VarCode, PCode, .VarName, "", .ValueCount, .beginDate, .endDate))
                    End If
                End If
            End With
        Next
        Return True
    End Function

    Public Overrides Function GetResultCount(QuickCount As Boolean) As Boolean
        Cancelled = False
        MyBase.GetResultCount(QuickCount)
        If QuickCount Then
            For Each ser As HISCentral.SeriesRecord In SelectedSeries
                With ser
                    DataCount += .ValueCount
                End With
            Next
        End If
        Return True
    End Function

    ''' <summary>
    ''' SelectedSeries property must be filled before calling this
    ''' </summary>
    ''' <returns>True if successful</returns>
    Public Overrides Function GetResults() As Boolean
        Try
            Cancelled = False
            Dim DataCount As Integer = 0

            lstData.Clear()

            Dim cnt As Integer = 0
            For Each ser As HISCentral.SeriesRecord In SelectedSeries
                With ser
                    If Not SetProgress(cnt, SelectedSeries.Count - 1, String.Format("Getting results for {0} ({1}); {2} values so far...", Strings.Left(.Sitename, 25), IIf(.conceptKeyword = "", .VarName.Trim, .conceptKeyword.Trim), DataCount)) Then Return False
                    cnt += 1
                    Cuahsi_1_0.Url = .ServURL
                    Cuahsi_1_1.Url = .ServURL
                    Dim ds As New DataSet
                    Dim xml As String = ""
                    'no way to tell whether source data uses WaterML 1.0 or 1.1; try 1.0 and if it fails, try 1.1
                    Try
                        xml = Cuahsi_1_0.GetValues(.location, .VarCode, StartDate.ToString("yyyy-MM-ddT00:00:00"), EndDate.ToString("yyyy-MM-ddT00:00:00"), "")
                    Catch ex As Exception
                        xml = Cuahsi_1_1.GetValues(.location, .VarCode, StartDate.ToString("yyyy-MM-ddT00:00:00"), EndDate.ToString("yyyy-MM-ddT00:00:00"), "")
                    End Try
                    ds.ReadXml(New IO.MemoryStream(New System.Text.ASCIIEncoding().GetBytes(Xml)))

                    If Not (ColumnExists(ds, "sitecode", "sitecode_Text") AndAlso ColumnExists(ds, "variablecode", "variablecode_Text")) Then Return False

                    Dim StationID As String = ""
                    With ds.Tables("sitecode").Rows(0)
                        StationID = .Item("Network") & ":" & .Item("sitecode_Text")
                    End With
                    Dim StationName As String = ds.Tables("sourceInfo").Rows(0).Item("siteName")
                    Dim PCode As String = ""
                    With (ds.Tables("variablecode").Rows(0))
                        PCode = .Item("vocabulary") & ":" & .Item("variablecode_Text")
                    End With
                    With ds.Tables("variable").Rows(0)
                        Dim DataType As String = ""
                        If ColumnExists(ds, "variable", "dataType") Then DataType = TestNull(.Item("dataType"), "")
                        If Not String.IsNullOrEmpty(DataType) Then PCode &= "/DataType=" & .Item("dataType") Else Debug.Print("not")
                        Dim ParmName As String = ds.Tables("variable").Rows(0).Item("variableName")
                    End With
                    Dim Units As String = ""
                    If ColumnExists(ds, "units", "unitsAbbreviation") Then Units = ds.Tables("units").Rows(0).Item("unitsAbbreviation")
                    Dim DepthM As String = ""

                    If StationID <> "" AndAlso PCode <> "" AndAlso
                       ColumnExists(ds, "value", "DateTime") AndAlso
                       ColumnExists(ds, "value", "Value_Text") Then
                        With ds.Tables("value")
                            For i As Integer = 0 To .Rows.Count - 1
                                Dim DateTime As Date = .Rows(i).Item("DateTime")
                                Dim Result As String = .Rows(i).Item("Value_Text")
                                Dim RCode As String = ""
                                If ColumnExists(ds, "value", "censorCode") Then RCode = TestNull(.Rows(i).Item("censorCode"), "")
                                If RCode <> "" Then RCode = RCode.Replace("lt", "<").Replace("gt", ">").Replace("nc", "").Replace("nd", "<").Replace("pnq", "P")
                                lstData.Add(New WRDB.Project.clsDataRecord(StationID, DateTime, PCode, Result, , RCode, , DepthM))
                                DataCount += 1
                            Next
                        End With
                        If dictParameters.ContainsKey(PCode) Then dictParameters(PCode).Units = Units
                    End If
                End With
            Next
            Return True
        Catch ex As Exception
            LastException = ex
            Return False
        End Try
    End Function

    ''' <summary>
    ''' Get all series for selected networks in area of interest; this internal list is refreshed every time the stations listview is filled
    ''' </summary>
    ''' <remarks></remarks>
    Private Function GetSeries() As Boolean
        Try
            dictSeries.Clear()

            If SelectedNetworkIDs.Count = 0 Then Return False

            Dim HISBox As New HISCentral.Box
            With HISBox
                .xmin = AreaOfInterest.Left
                .xmax = AreaOfInterest.Right
                .ymin = AreaOfInterest.Top
                .ymax = AreaOfInterest.Bottom
            End With

            Dim arSeries() As HISCentral.SeriesRecord = HISCentralService.GetSeriesCatalogForBox(HISBox, "", SelectedNetworkIDs.ToArray, StartDate.ToString("MM/dd/yyyy"), EndDate.ToString("MM/dd/yyyy"))

            If arSeries.Length = 0 Then
                Return False
            End If

            Dim lstNetworks As New Generic.List(Of String)

            'note: the series dictionary may have fewer entries than arSeries because by inspection arSeries has duplicates (where ConceptKeyword is "Unspecified")

            For i As Integer = 0 To arSeries.Length - 1
                With arSeries(i)
                    Dim key As String = .ServCode & "/" & .VarName & "/" & .location & "/" & .samplemedium & "/" & .datatype & "/" & .valuetype & "/" & .timeunits
                    If Not dictSeries.ContainsKey(key) Then dictSeries.Add(key, arSeries(i))

                    If Not lstNetworks.Contains(.ServCode) Then lstNetworks.Add(.ServCode)

                    'If Not dictStations.ContainsKey(.location) Then
                    '    dictStations.Add(.location, New clsStation(.location, .location, .Sitename, .samplemedium, .ServCode, dictNetworks(.ServCode).NetworkName, .latitude, .longitude, "", ""))
                    'End If

                    'If Not dictParameters.ContainsKey(.VarCode) Then
                    '    dictParameters.Add(.VarCode, New clsParameter(.location, .VarCode, .VarCode, .VarName, "", .ValueCount, .beginDate, .endDate))
                    'End If
                End With
            Next
            Return True
        Catch ex As Exception
            Throw
            Return False
        End Try
    End Function

End Class
